package dgdb2d;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Set;
import java.util.UUID;

import com.tinkerpop.blueprints.pgm.Element;

/**
 * Abstrakcyjna klasa bazowa opisujaca element grafu (wierzcholek lub krawedz). Implementowany jest interfejs Element
 * standardu Blueprints.
 * 
 * @author Dominik Zielinski, Patryk Chaber
 * @version 0.42
 * 
 */
public abstract class GDBElement implements Element, Serializable {

	private static final long serialVersionUID = 5464169362739882274L;

	/**
	 * Identyfikator elementu.
	 */
	private String id;

	/**
	 * Wlasciwosci elementu. Wlasciwosci sa zapisywane w postaci klucz-wartosc.
	 */
	private HashMap<String, String> properties;

	/**
	 * Konstruktor bezparametrowy. Identyfikator elementu jest generowany losowo.
	 */
	public GDBElement() {
		this(UUID.randomUUID().toString());
	}

	/**
	 * Konstruktor inicjalizujacy ID elementu wybrana wartoscia.
	 * 
	 * @param id Wybrane ID elementu.
	 */
	public GDBElement(String id) {
		this.id = id;
		this.properties = new HashMap<String, String>();
	}

	/**
	 * Konstruktor wczytujacy wlasciwosci i ID obiektu na podstawie danych zawartych w drzewie XML.
	 * Implementacja pozostawiona ze wzgledu na mechanizm RMI. Metoda ta nie jest wywolywana z poziomu klienta.
	 * 
	 * @param root Korzen drzewa XML.
	 */
	public GDBElement(org.jdom2.Element root) {
		throw new IllegalArgumentException();
	}

	@Override
	public Object getProperty(String key) {
		return properties.get(key);
	}

	@Override
	public Set<String> getPropertyKeys() {
		return properties.keySet();
	}
	
	@Override
	public void setProperty(String key, Object value) {
		properties.put(key, value.toString());
		if(this instanceof GDBVertex){
			ClientGDB.gdb.setVertexProperty((Object)id,key,value);
		} else {
			ClientGDB.gdb.setEdgeProperty((Object)id,key,value);
		}
	}

	@Override
	public Object removeProperty(String key) {
		if (!properties.containsKey(key))
			return null;
		Object r = properties.get(key);
		if(this instanceof GDBVertex){
			ClientGDB.gdb.removeVertexProperty((Object)id,key);
		} else {
			ClientGDB.gdb.removeEdgeProperty((Object)id,key);
		}
		properties.remove(key);
		return r;
	}

	@Override
	public Object getId() {
		return this.id;
	}

	/**
	 * Pobieranie wlasciwosci elementu w formie drzewa XML.
	 * Implementacja pozostawiona ze wzgledu na mechanizm RMI. Metoda ta nie jest wywolywana z poziomu klienta.
	 * 
	 * @return Drzewo XML zawierajace informacje o wlasciwosciach elementu.
	 */
	protected org.jdom2.Element getPropertiesAsElement() {
		throw new IllegalArgumentException();
	}

	@Override
	public String toString() {
		String r = ""; 
		if(this instanceof GDBEdge){
			r += "e";
		} else {
			r += "v";
		}
		r += "["+id+"]";
		return r;
	}

	/**
	 * Abstrakcyjna metoda zapisujaca element do dokumentu XML.
	 */
	protected abstract void save();

}
